<template>
  <div class="uploadX" @click.stop="">
    <div class="all one" v-show="!props.noUpload">
      <el-upload ref="elUploadDom" class="upload-box" v-if="props.which == 'one'"
                 v-model:file-list="dataList"
                 :drag="props.drag"
                 :auto-upload="props.autoUp" :action="props.action" :multiple="props.multiple"
                 :accept="props.accept" :on-change="changeFn"
                 :limit="Number(props.limit)" :on-exceed="exceedFn"
                 :list-type="props.type">
        <div class="default">
          <slot>
            <div class="addIcon">
              <iconX type="Plus" size="30"/>
            </div>
          </slot>
        </div>
        <template #file="{file}">
          <span class="fileSlot">
          <slot name="file" :data="file">
            <div>
              <!-- 自定义图标 -->
              <slot v-if="slotNameFn(file)" :name="slotNameFn(file)" :file="file">

              </slot>
              <!-- 默认支持的图标 -->
              <div v-else class="fileBox">
                <el-image class="item" v-if="isFile(file)==1" :src="file.url"
                          :preview-src-list="[file.url]" :initial-index="0" fit=""
                          preview-teleported lazy/>
                <video class="item" v-else-if="isFile(file)==2" :src="file.url" controls ref="videoDom">
                  浏览器不支持该视频标签
                </video>
                <div v-else class="nameBox">
                  <slot name="other" :file="file"><span class="fileName">{{ file.name }}</span></slot>
                </div>
              </div>


              <!-- 遮蔽层按钮 -->
              <div class="bnList el-upload-list__item-actions">
                <span class="remove el-upload-list__item-delete" @click="showFile(file)">
                  <iconX type="zoomIn" size="20"/>
                </span>

                <span v-show="!props.noAdd || !props.noDel"
                      class="remove el-upload-list__item-delete" @click="remove(file)">
                  <iconX type="Delete" size="20"/>
                </span>
              </div>
            </div>
          </slot>
            </span>
        </template>
      </el-upload>
    </div>

    <div>
      <el-image-viewer v-if="showImage" :url-list="showImageList" teleported
                       @close="showImage = false" hide-on-click-modal/>
      <!-- 播放视频 -->
      <div v-if="showVideo">
        <dialog-x :title="'正在播放：'+videoInfo.name" :show="showVideo"
                  @close="showVideo = false" to-body
                  :showFooterBn="false">
          <video :src="videoInfo.url" style="width: 100%;height: 500px;" controls/>
        </dialog-x>
      </div>
    </div>
  </div>
</template>

<script setup>
import { onUnmounted, ref, watch} from 'vue'
import iconX from './xhykIcon.vue'
import DialogX from './xhykDialog.vue'
import { ElUpload,ElImage,ElImageViewer } from 'element-plus'

const props = defineProps({
  modelValue: {
    type: Object,
    // raw.type 必须要有
    default: undefined
  },

  type: {
    type: String,
    default: 'picture-card'
  },
  // 非动态监听
  list: {
    type: Object,
    default: []
  },

  // 显示添加框
  noAdd: {
    type: Boolean,
    default: false
  },

  // 使用哪个
  which: {
    type: String,
    default: 'one'
  },
  // 回调函数：图标插槽名称
  slotNameFn: {
    type: Function,
    default: file => {
      return undefined
    }
  },

  // 自动上传文件
  autoUp: {
    type: Boolean,
    default: false
  },

  // 支持拖拽
  drag: {
    type: Boolean,
    default: true
  },

  // 请求地址
  action: {
    type: String,
    default: '#'
  },

  // 支持多选
  multiple: {
    type: Boolean,
    default: true
  },

  // 文件类型
  accept: {
    type: String,
    default: 'image/*,video/*'
  },

  // 文件大小。以字节为单位。1kb = 1024字节。1mb = 1024kb
  size: {
    type: [String, Number],
    default: undefined
  },

  // 文件发生改变前回调函数
  changeFn: {
    type: Function,
    default: undefined
  },
  startData: {
    type: Object,
    default: []
  },

  // 上传最大数量
  limit: {
    type: [Number, String],
    default: 100
  },
  // 改变前函数。返回false则不添加
  beforeFn: {
    type: Function,
    default: undefined
  },
  // 是否使用自带的显示图片视频
  autoShow: {
    type: Boolean,
    default: true
  },
  // 不显示上传，只用来预览
  noUpload: {
    type: Boolean,
    default: false
  },
  // 在不显示添加的情况下，可以单独不显示删除
  noDel: {
    type: Boolean,
    default: false
  },
})
// showFile：选择的文件
const emit = defineEmits(['update:modelValue', 'showFile', 'change', 'del'])

const elUploadDom = ref({})

// 文件列表
const dataList = ref([])
watch(() => dataList.value, newV => {
  emit('update:modelValue', dataList.value || [])
}, {immediate: true, deep: true})


// 文件添加图片后的回调函数
const changeFn = (file) => {
  if (props.beforeFn != undefined && typeof props.beforeFn == 'function') {
    const result = props.beforeFn(file)
    if (result == false) {
      dataList.value = dataList.value.filter(item => item.uid != file.uid)
      return result
    }
  }
  if (props.size != undefined) {
    // 处理文件大于这个尺寸的文件
    if (file.size > props.size) {
      dataList.value = dataList.value.filter(item => item.uid != file.uid)
    }
  }
  return false
}

// 超过数量时回调函数
const exceedFn = (files, uploadFiles) => {
  let tempList = [...dataList.value, ...files]
  // console.log(JSON.parse(JSON.stringify(tempList)))
  if (tempList.length > Number(props.limit)) {
    // [1,2,3,4,5,6,7,8,9,0]  3
    tempList = tempList.slice(tempList.length - Number(props.limit), tempList.length)
  }
  // console.log(tempList)
  // 获取后面的文件
  while (dataList.value.length > 0) {
    elUploadDom.value.handleRemove(dataList.value[0])
  }
  tempList.forEach(item => {
    // dataList.value.shift()
    if (item.url) {
      elUploadDom.value.handleStart(item.raw)
    } else {
      elUploadDom.value.handleStart(item)
    }
  })
}


// 判断文件类型
const isFile = file => {
  // 如果是自定义插槽则不显示
  if (props.slotNameFn(file)) {
    return 0
  }
  // 如果是超过limit的文件，file是raw对象
  const type = file?.raw?.type || ''
  if (type.indexOf('image') != -1) {
    return 1
  } else if (type.indexOf('video') != -1) {
    return 2
  }
  return 0
}

// 显示预览
let showImage = ref(false)
let showVideo = ref(false)
// 预览列表
const showImageList = ref([])
const videoInfo = ref({})
// 图片处理函数
const videoDom = ref(undefined)
const showFile = file => {
  const type = isFile(file)
  emit('showFile', {file, type})
  if (!props.autoShow) {
    return;
  }
  switch (type) {
    case 1:
      showImageList.value = [file.url]
      showImage.value = true
      break
    case 2:
      videoInfo.value = {
        name: file.name,
        url: file.url
      }
      showVideo.value = true
      break
  }


}
const download = file => {
  console.log('下载', file)
}
const remove = file => {
  dataList.value = dataList.value.filter(item => item.uid != file.uid)
  props.list.filter(item => item.uid != file.uid)
  emit('del', file)
}


// 不显示添加框
const showAdd = ref("none")
watch(() => props.noAdd, newV => {
  showAdd.value = props.noAdd ? 'none' : 'block'
}, {immediate: true, deep: true})


watch([() => props.modelValue, () => props.list], () => {
  if (props.modelValue == undefined) {
    dataList.value = props.list
  } else {
    dataList.value = props.modelValue
  }
}, {immediate: true, deep: true})

onUnmounted(() => {
  dataList.value = []
})


defineExpose({
  showFile
})
</script>

<style scoped lang='scss'>
.one {
  height: auto;
}

// 添加图标样式
:deep(.el-upload-dragger) {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}


/* 内容区插槽 */
.fileSlot {
  //background-color: red;
  position: relative;
  flex: 1 1 auto;
}

.fileBox {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  //width: 100%;
  //height: 100%;
  .item {
    width: 100%;
    height: 100%;
  }
}

// 默认内容
.nameBox {
  height: 100%;
  text-align: center;
  display: flex;
  justify-content: center;
  flex-direction: column;

  .fileName {
    word-break: break-all;
  }
}

// 添加框
:deep(.el-upload) {
  display: v-bind(showAdd);
}
</style>